/**
 *  目标： 把大多数 页面 都有的 分页、搜索、表格功能都抽离出来
 *  
 *  把相同的代码直接抽离，把不同的代码以 参数 的形式进行传入
 *  还要考虑出参(返回值)
 *  不同的东西：
 *    1. 请求的接口
 *    2. 搜索需要的参数
 * 
 *  返回值(出参)
 *    1. 表格数据，数组 list
 *    2. 总条数 total，当前面 pageNum ，页容量 pageSize
 *    3. 提供一个请求的函数，让外部调用
 */

import { Ref, reactive, ref, toRefs, watch } from 'vue';
import axios, { CancelToken, CancelTokenSource } from 'axios';

// fetch 是 请求表格数据的函数 ， 所有的请求表格数据的函数 函数签名 : ()=>TS<data.list>
export function useTable<T>(fetch: (params: any, token?: CancelToken) => TS<T>, searchParams?: Object) {
  const params = reactive<IUserListParams>({
    keyword: '', pageNum: 1, pageSize: 10
  })

  const list = ref<T[]>([]);
  const total = ref(0);

  // 是否正在请求
  let pending = false;
  let source: CancelTokenSource;
  const fetchApi = () => {
    let CancelToken = axios.CancelToken;
    source = CancelToken.source();
    // 请求正在发送
    pending = true;
    fetch(Object.assign(params, searchParams), source.token).then(res => {
      if (res.code === 200) {
        // 渲染数据
        // @ts-ignore
        list.value = res.data.list;
        total.value = res.data.total
      }
    }).finally(() => {
      // 请求结束
      pending = false
    })
  }
  fetchApi();

  // toRefs 将响应式对象里面的每个属性都变成响应式的 , 把对象里面的每个属性变成 Ref 对象
  const { pageNum, pageSize } = toRefs(params)

  // 监听 当前面和页容易变化，发请求
  watch([pageNum, pageSize], ([__, newSize], [_, oldSize]) => {
    // page变化了，要把 pageNum 重置为 1
    if (newSize !== oldSize) {
      params.pageNum = 1
    }
    if (pending) {
      source.cancel();
    }
    fetchApi();
  })


  return {
    list, total, pageNum, pageSize, fetchApi
  }
}